 import  RuleStack from "./RuleStack.js"
/**
 * 语法分析
 */
let tem=new Array()
 let objs=new Array()
 let tree;
export default class Syntax{
    constructor(wordsIds ){
        this. sentence=new Array();

        this.root=0;
    }


    run(wordsIds,ruleStack){
        this. ruleStack=ruleStack;
        this.wordsIds=wordsIds;
        this.n=0;
        let obj=this.ergodicRules()
        tem.push(obj);
        debugger
        for( ; this.n< wordsIds.length; this.n++){

            tem.push( wordsIds[this.n].type)
            objs.push(wordsIds[this.n].data)
           let obj=this.ergodicRules()
            tem.push(obj);

            if(obj ==""){
                tem.pop()
            }
        }
        this.ergodicRules()

        return tree;
    }

    /**
     * 语法分析 从下往上 查找
     * @returns {string}
     */
    ergodicRules(){

        if(this.ruleStack.length<1){
            return "";
        }
        for(let i=this.ruleStack.length;i>0;i--){
            let rules=this.ruleStack[i-1];
            for(let n=rules.rules.length;n>0;n--){
               let rule=rules.rules[n-1];
               let isz=0;
                for(let l=0;l<rule.length-1;l++){
                    if(rule[l]==tem[l]){
                        isz++;
                    }else {


                        if(isz>0&&isz>l-1&&l<rule.length-1){
                            this. embedded(l,rule[l]);
                            if(rule[l]==tem[l]){
                                isz++;
                            }
                        }
                    }

                }
                if(isz==rule.length-1&&isz==tem.length){
                   let obj= eval("( function ()"+rule[rule.length-1]+")()")
                    let objs2= obj
                    return rules.id;
                     ;
                }
            }
        }
        return "";
    }

    /**
     *  嵌套 匹配
     * 把前面的数据保存到栈里面；
     * @param index
     * @param type
     */
    embedded(index,type){
        let temLength =tem.length
        let tems=new Array();
        let objsz=new Array();
        for(let i=0;i<index;i++){
            tems.push(tem.shift())
            objsz.push(objs.shift())
        }
        if(type=="statement"||type=="结构B"||type=="动作B"){
            if(this.n>=this.wordsIds.length){
                tems.push(...tem)
                objsz.push(...objs)
                tem=tems
                objs=objsz
                return;
            }
            this.statementRun();
            tems.push(...tem)
            objsz.push(...objs)
            tem=tems
            objs=objsz
            return;
        }

        let obj=this.expect(type)
        if(obj==false){
            tems.push(...tem)
            objsz.push(...objs)
            tem=tems
            objs=objsz
            return;
        }
        tem.push(obj);
        if(obj ==""){
            tem.pop()
        }

        for( ; this.n+1< this.wordsIds.length-1; ){

            this.n++
            tem.push( this.wordsIds[this.n].type)
            objs.push(this.wordsIds[this.n].data)
             let obj=this.expect(type)
            if(obj==false){
                for(let l=tem.length;l>temLength;l--){
                    tem.pop()
                    objs.pop()
                    this.n--;
                }
                tems.push(...tem)
                objsz.push(...objs)
                tem=tems
                objs=objsz
                return;
            }
            if(!obj){
                return;
            }
             tem.push(obj);
             if(obj ==""){
                 tem.pop()
             }
             if(obj==type){
                 tems.push(...tem)
                 objsz.push(...objs)
                 tem=tems
                 objs=objsz
                 return;
             }
        }

    }
    statementRun(){

        let obj2=this.ergodicRules()
        tem.push(obj2);

        if(obj2 ==""){
            tem.pop()
        }
        if(obj2=="statement"){
            return obj2;
        }
        for( ; this.n< this.wordsIds.length-1; ){
            this.n++
            tem.push( this.wordsIds[this.n].type)
            objs.push(this.wordsIds[this.n].data)

            let obj=this.ergodicRules()
            tem.push(obj);

            if(obj ==""){
                tem.pop()
            }
            if(obj=="statement"){
                return obj;
            }
        }
    }

    findRules(id){

        for(let n=0;n<this.ruleStack.length;n++){
            let rules=this.ruleStack[n]
            if(rules.id==id){
                return true;
            }
        }
        return false
    }


    /**
     * 预期的类型，如果找不到返回 false
     * 从上往下查找
     * @param type
     * @returns {boolean}
     */
    expect(type){
        let rulez;
        for(let n=0;n<this.ruleStack.length;n++){
            let rules=this.ruleStack[n]
            if(rules.id==type){
                rulez=rules.rules;
            }
        }

        if(typeof(rulez) == "undefined"){
            return false;
        }


        for(let n=rulez.length;n>0;n--){
            let rule=rulez[n-1];
            let isz=0;
            for(let l=0;l<rule.length-1;l++){
                if(rule.length-1<tem.length){
                    break;
                }
                if(isz==tem.length){
                   this. embedded2(rule[l])
                }
                if(rule[l]==tem[l]){
                    isz++;
                }else {
                    if(rule.length-1==tem.length){
                        if(isz>l-1&&l<rule.length-1){
                            this. embedded(l,rule[l+1]);
                            if(rule[l]==tem[l]){
                                isz++;
                            }
                        }else {
                            this. expect(type)
                            if(rule[l]==tem[l]){
                                isz++;
                            }
                        }
                    }

                }

            }

            if(isz==rule.length-1&&isz==tem.length){
                let obj= eval("( function ()"+rule[rule.length-1]+")()")
                let objs2= obj

                return type;
                ;
            }

     }
        return false;
    }

    /**
     * 嵌套逾期2
     */
    embedded2(type){
        let temLength =tem.length
        for( ; this.n< this.wordsIds.length-1; ){
            if(this.n>15){
                debugger
            }
            this.n++
            tem.push( this.wordsIds[this.n].type)
            objs.push(this.wordsIds[this.n].data)
            if(this.wordsIds[this.n].type ==type){
                return;
            }
            let obj=this.embedded(temLength,type)
            if(obj==false){ //错误还原
                for(let l=tem.length;l>temLength;l--){
                    tem.pop()
                    objs.pop()
                    this.n--
                }
                return;
            }
            if(!obj){
                return;
            }
            tem.push(obj);
            if(obj ==""){
                tem.pop()
            }
            if(obj==type){
                return;
            }

        }
    }

}


class   TreeNode {
    constructor(type, ...args){
        this.type=type;
        this.data=new Array();
      //  this.next=objs[0]
        for(let i=0;i<args.length;i++){
            this.data.push(objs[args[i]-1])

        }

        tem=new Array();
        objs=new Array();
        objs.push(this)

    }
 }
